package tech.xiaozai.rbac.security.authentication;

import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import tech.xiaozai.rbac.security.JWTWorker;
import tech.xiaozai.rbac.security.LoadPermissionAfterIOCRunning;
import tech.xiaozai.rbac.security.MyUserDetails;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.List;

/**
 * @author xiaozai
 * @version 1.0
 * @date 2020-09-23 16:58
 *
 *  就是用来查验令牌的过滤器
 */
public class JwtAuthenticationFilter  extends OncePerRequestFilter {

    @Autowired
    private JWTWorker jwtWorker;

    @Autowired
    private LoadPermissionAfterIOCRunning running;

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {

        String authorization = httpServletRequest.getHeader("Authorization");
        if(authorization!=null) {
            try {
                String prefix = "Bearer ";
                String token = authorization.substring(authorization.indexOf(prefix) + prefix.length());

                DecodedJWT jwt = jwtWorker.verify(token);
                //执行到此行说明令牌有效 ,要构建一个认证主体，放进安全上下文

                //先从安全上下文中取出认证主体，管它有没有，先取一遍，没有的话我放一个进去
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                if (authentication == null) {
                    MyUserDetails user = new MyUserDetails();
                    user.setId(jwt.getClaim("userId").asLong());

                    List<String> roleIds = jwt.getClaim("roleIds").asList(String.class);
                    httpServletRequest.setAttribute("roleIds",roleIds);


                    //从权限表中查询该用户所有角色的所有权限集合,
                    // 用于在投票器(PreInvocationAuthorizationAdviceVoter)中去比对
                    Collection<GrantedAuthority> authorities = running.keywords(roleIds);

                    user.setAuthorities(authorities);

                    UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, null, authorities);
                    SecurityContextHolder.getContext().setAuthentication(auth);
                }

            } catch (Exception e) {
                //令牌无效，啥也不干，后续的流程识别不了用户，就当请求不允许
                e.printStackTrace();
            }
        }
        filterChain.doFilter(httpServletRequest,httpServletResponse);

    }
}
